home *** CD-ROM | disk | FTP | other *** search
- /* << ACE >>
-
- -- Amiga BASIC compiler --
-
- ** Symbol Table Management & Code Generation **
- ** Copyright (C) 1998 David Benn
- **
- ** This program is free software; you can redistribute it and/or
- ** modify it under the terms of the GNU General Public License
- ** as published by the Free Software Foundation; either version 2
- ** of the License, or (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program; if not, write to the Free Software
- ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- Author: David J Benn
- Date: 26th October-25th November, 2nd-13th December 1991,
- 27th January 1992, 8th-9th, 25th February 1992,
- 21st April 1992,
- 8th,9th,13th,14th,28th June 1992,
- 2nd,3rd,4th,5th,17th,26th,28th,29th July 1992,
- 1st-3rd,8th,9th August 1992,
- 6th,22nd,29th December 1992,
- 13th January 1993,
- 2nd,28th February 1993,
- 12th,20th April 1993,
- 15th-18th,28th December 1993,
- 7th January 1994,
- 26th February 1994,
- 12th June 1994,
- 20th August 1994,
- 10th September 1994
- */
-
- #include <string.h>
- #include "symvar.h"
-
- /* -- general functions -- */
- void kill_all_lists (void)
- {
- lev = ONE;
- while (lev >= ZERO)
- {
- kill_symtab ();
- --lev;
- }
- puts ("freeing code list...");
- kill_code (); /* all other lists are freed by cleanup() */
- }
-
- /* -- symbol table functions -- */
- void new_symtab (void)
- {
- /* create a new symbol table
- at current level.
- */
-
- if ((tab_head[lev] = (SYM *) sym_alloc (sizeof (SYM), MEMF_ANY)) == NULL)
- {
- printf ("Can't allocate memory for symbol table!\n");
- early_exit = TRUE;
- kill_all_lists ();
- cleanup ();
- }
- tab_head[lev]->next = NULL;
- }
-
- void kill_symtab (void)
- {
- /* free memory held by
- symbol table.
- */
-
- free_sym_alloc ();
- }
-
- void find_tab_tail (void)
- {
- /* find the end of the
- symbol table at current
- level.
- */
-
- tab_tail = tab_head[lev];
- while (tab_tail->next != NULL)
- tab_tail = tab_tail->next;
- }
-
- BOOL exist (char *name, int obj)
- {
- int oldlevel;
-
- oldlevel = lev;
-
- if ((obj == subprogram) || (obj == function) ||
- (obj == definedfunc) || (obj == extfunc) || (obj == extvar) ||
- (obj == constant) || (obj == structdef))
- lev = ZERO;
-
- curr_item = tab_head[lev]->next;
- while (curr_item != NULL)
- {
- if ((strcmp (curr_item->name, name) == 0) && (curr_item->object == obj))
- {
- lev = oldlevel;
- return (TRUE);
- }
- else
- curr_item = curr_item->next;
- }
-
- lev = oldlevel;
- return (FALSE);
- }
-
- void enter (char *name, int typ, int obj, int dims)
- /* enter a symbol into symbol table */
- {
- int i;
-
- /* allocate memory for info' */
- if ((new_item = (SYM *) sym_alloc (sizeof (SYM), MEMF_ANY)) == NULL)
- {
- printf ("Can't allocate memory for symbol table item!\n");
- early_exit = TRUE;
- kill_all_lists ();
- cleanup ();
- }
-
- if ((new_item->name = (char *) sym_alloc (strlen (name) + 1, MEMF_ANY)) == NULL)
- {
- printf ("Can't allocate memory for symbol table item!\n");
- early_exit = TRUE;
- kill_all_lists ();
- cleanup ();
- }
-
- /* fill the node with info' */
- strcpy (new_item->name, name);
- new_item->type = typ;
- new_item->object = obj;
- new_item->dims = dims;
-
- /* string defaults */
- if ((typ == stringtype) && (obj != array))
- {
- new_item->new_string_var = TRUE;
- new_item->decl = undeclared;
- new_item->size = MAXSTRLEN;
- }
-
- if ((obj != label) && (obj != function) && (obj != constant) &&
- (obj != extvar) && (obj != extfunc) && (obj != structdef))
- {
- /* how many bytes to reserve? */
- if ((typ == shorttype) && (obj != array))
- addr[lev] += 2;
- else
- addr[lev] += 4; /* long, single, string, array, sub, structure */
-
- new_item->address = addr[lev];
- }
- else
- new_item->address = 0;
-
- new_item->level = lev;
- new_item->shared = FALSE; /* shared may be explicitly SET later */
-
- /* array? -> store index maxima */
- if (obj == array)
- {
- if ((new_item->index = (SHORT *) sym_alloc ((dims + 1) * 2, MEMF_ANY)) == NULL)
- {
- printf ("Array index storage allocation error.\n");
- early_exit = TRUE;
- kill_all_lists ();
- cleanup ();
- }
- else
- for (i = 0; i <= dims; i++)
- new_item->index[i] = dimsize[i];
- }
-
- /* setup for structure definition */
- if (obj == structdef)
- {
- if ((new_item->structmem =
- (STRUCM *) sym_alloc (sizeof (STRUCM), MEMF_ANY)) == NULL)
- {
- printf ("Can't allocate memory for an initial structdef node!\n");
- early_exit = TRUE;
- kill_all_lists ();
- cleanup ();
- }
- else
- {
- new_item->structmem->next = NULL;
- new_item->size = 0;
- }
- }
-
- /* link item into symbol table */
-
- find_tab_tail ();
- /* find_tab_tail(tab_head[lev]); */
-
- tab_tail->next = new_item;
- new_item->next = NULL;
- curr_item = new_item;
- }
-
- /*
- void show_table_item(SYM *item)
- {
- printf("%10s\t",item->name);
- showtyp(item->type);
- showobj(item->object);
- printf("%5d\t%5d\t%5d\n",item->dims,item->address,item->level);
- }
- */
-
- /* --code generator functions-- */
-
- void create_lists (void)
- {
- /* create code, DATA, BSS, XREF and BASIC DATA lists */
-
- data = (DATA *) alloc (sizeof (DATA), MEMF_ANY);
- if (data == NULL)
- {
- cleanup ();
- }
- else
- {
- curr_data = data;
- data->next = NULL;
- }
-
- bss = (BSS *) alloc (sizeof (BSS), MEMF_ANY);
- if (bss == NULL)
- {
- cleanup ();
- }
- else
- {
- curr_bss = bss;
- bss->next = NULL;
- }
-
- xref = (XREF *) alloc (sizeof (XREF), MEMF_ANY);
- if (xref == NULL)
- {
- cleanup ();
- }
- else
- {
- curr_xref = xref;
- xref->next = NULL;
- }
-
- basdata = (BASDATA *) alloc (sizeof (BASDATA), MEMF_ANY);
- if (basdata == NULL)
- {
- cleanup ();
- }
- else
- {
- curr_basdata = basdata;
- basdata->next = NULL;
- }
-
- code = (CODE *) alloc_code (" ", " ", " "); /* first node is a dummy */
- if (code == NULL)
- {
- cleanup ();
- }
- else
- {
- curr_code = code;
- code->next = NULL;
- }
- }
-
- BOOL is_a_label (char *opc)
- {
- int cc = 0;
-
- while (opc[cc] != '\0')
- cc++;
- if (opc[cc - 1] == ':')
- return (TRUE);
- else
- return (FALSE);
- }
-
- void write_code (CODE * line)
- {
- if (strcmp (line->opcode, "nop") != 0)
- {
- if (!is_a_label (line->opcode))
- {
- fprintf (dest, "\t%s", line->opcode);
- fprintf (dest, "\t%s", line->srcopr);
- if (line->destopr[0] != ' ')
- fprintf (dest, ",%s\n", line->destopr); /* comma & destopr */
- else
- fprintf (dest, "\n"); /* no destopr, so just LF */
- }
- else
- fprintf (dest, "%s\n", line->opcode); /* label starts in 1st column */
- }
- }
-
- BOOL label_undef (CODE * node)
- {
- char buf[50];
-
- if ((strcmp (node->opcode, "jmp") == 0) ||
- (strcmp (node->opcode, "jsr") == 0))
- {
- if (strcmp (node->destopr, "* ") == 0)
- {
- /* undefined label at time of jmp/jsr */
- strcpy (buf, node->srcopr);
- strcat (buf, ":\0");
- /* has it been defined since jmp/jsr? */
- if (exist (buf, label))
- {
- strcpy (node->destopr, " ");
- return (FALSE);
- } /* not UNdefined */
- else
- {
- early_exit = TRUE;
- return (TRUE); /* undefined */
- }
- }
- else
- return (FALSE); /* not UNdefined */
- }
- else
- return (FALSE); /* not a branch instruction */
- }
-
- void undef_label_check (void)
- {
- BOOL past_head = FALSE;
-
- /* check for undefined labels */
- curr_code = code;
- while (curr_code->next != NULL)
- {
- if (past_head)
- {
- if (label_undef (curr_code))
- {
- _error (8);
- printf ("'%s'\n", curr_code->srcopr);
- }
- }
- curr_code = curr_code->next;
- if (!past_head)
- past_head = TRUE;
- }
- if (label_undef (curr_code))
- {
- _error (8);
- printf ("'%s'\n", curr_code->srcopr);
- }
- }
-
- void kill_code (void)
- {
- BOOL past_head = FALSE;
- CODE *curr, *temp;
-
- curr = code;
-
- do
- {
- temp = curr;
- curr = curr->next;
- if (past_head)
- {
- if (!early_exit)
- write_code (temp);
-
- /* free all the struct's memory */
- free_code (temp);
- }
-
- if (!past_head)
- past_head = TRUE;
- }
- while (curr != NULL);
-
- /* free the dummy head node's memory */
- free_code (code);
- }
-
- void gen (char *opcode, char *srcopr, char *destopr)
- {
- /* allocate memory for a new node & each field */
- if ((new_code = (CODE *) alloc_code (opcode, srcopr, destopr)) == NULL)
- {
- printf ("Can't allocate memory for code node!\n");
- early_exit = TRUE;
- kill_all_lists ();
- cleanup ();
- }
-
- /* fill code struct */
- strcpy (new_code->opcode, opcode);
- strcpy (new_code->srcopr, srcopr);
- strcpy (new_code->destopr, destopr);
-
- new_code->next = NULL;
- curr_code->next = new_code;
- curr_code = curr_code->next;
- }
-
- void change (CODE * cx, char *opcode, char *srcopr, char *destopr)
- {
- /* free the old fields */
- free_code_members (cx);
-
- /* allocate memory & insert new instruction & operands */
- if ((BOOL) alloc_code_members (cx, opcode, srcopr, destopr))
- {
- strcpy (cx->opcode, opcode);
- strcpy (cx->srcopr, srcopr);
- strcpy (cx->destopr, destopr);
- }
- else
- {
- printf ("Can't allocate memory for CODE node fields!\n");
- early_exit = TRUE;
- kill_all_lists ();
- cleanup ();
- }
- }
-
- /* --DATA list functions-- */
-
- BOOL exist_DATA (char *name)
- {
- DATA *curr;
- curr = data->next;
- while (curr != NULL)
- {
- if (strcmp (curr->name, name) == 0)
- return (TRUE);
- else
- curr = curr->next;
- }
- return (FALSE);
- }
-
- void enter_DATA (char *name, char *literal)
- {
- if (exist_DATA (name))
- return; /* already exists */
-
- /* allocate memory for a new node & each field */
- if ((new_data = (DATA *) alloc (sizeof (DATA), MEMF_ANY)) == NULL)
- {
- printf ("Can't allocate memory for DATA node!\n");
- early_exit = TRUE;
- kill_all_lists ();
- cleanup ();
- }
-
- if ((new_data->name = (char *) alloc (strlen (name) + 1, MEMF_ANY)) == NULL)
- {
- printf ("Can't allocate memory for DATA node name field!\n");
- early_exit = TRUE;
- kill_all_lists ();
- cleanup ();
- }
-
- if ((new_data->literal = (char *) alloc (strlen (literal) + 1, MEMF_ANY)) == NULL)
- {
- printf ("Can't allocate memory for DATA node literal field!\n");
- early_exit = TRUE;
- kill_all_lists ();
- cleanup ();
- }
-
- /* fill DATA struct */
- strcpy (new_data->name, name);
- strcpy (new_data->literal, literal);
-
- new_data->next = NULL;
- curr_data->next = new_data;
- curr_data = curr_data->next;
- }
-
- void write_data (void)
- {
- BOOL past_head = FALSE;
- DATA *curr, *temp;
-
- curr = data;
- if (curr->next != NULL)
- {
- fprintf (dest, "\n\tSECTION data,DATA\n\n");
- }
-
- do
- {
- temp = curr;
- curr = curr->next;
- if (past_head)
- {
- fprintf (dest, "%s\t%s\n", temp->name, temp->literal);
- }
- if (!past_head)
- past_head = TRUE;
- }
- while (curr != NULL);
- }
-
- /* --BSS list functions-- */
-
- BOOL exist_BSS (char *name)
- {
- BSS *curr;
- curr = bss->next;
- while (curr != NULL)
- {
- if (strcmp (curr->name, name) == 0)
- return (TRUE);
- else
- curr = curr->next;
- }
- return (FALSE);
- }
-
- void enter_BSS (char *name, char *store)
- {
- /* ignore if already exists, except if name is " "
- which is used for structure declarations */
- if ((exist_BSS (name)) && (strcmp (name, " ") != 0))
- return;
-
- /* allocate memory for a new node & each field */
- if ((new_bss = (BSS *) alloc (sizeof (BSS), MEMF_ANY)) == NULL)
- {
- printf ("Can't allocate memory for BSS node!\n");
- early_exit = TRUE;
- kill_all_lists ();
- cleanup ();
- }
-
- if ((new_bss->name = (char *) alloc (strlen (name) + 1, MEMF_ANY)) == NULL)
- {
- printf ("Can't allocate memory for BSS node name field!\n");
- early_exit = TRUE;
- kill_all_lists ();
- cleanup ();
- }
-
- if ((new_bss->store = (char *) alloc (strlen (store) + 1, MEMF_ANY)) == NULL)
- {
- printf ("Can't allocate memory for BSS node literal field!\n");
- early_exit = TRUE;
- kill_all_lists ();
- cleanup ();
- }
-
- /* fill BSS struct */
- strcpy (new_bss->name, name);
- strcpy (new_bss->store, store);
-
- new_bss->next = NULL;
- curr_bss->next = new_bss;
- curr_bss = curr_bss->next;
- }
-
- void write_bss (void)
- {
- BOOL past_head = FALSE;
- BSS *curr, *temp;
-
- curr = bss;
- if (curr->next != NULL)
- {
- fprintf (dest, "\n\tSECTION mem,BSS\n\n");
- }
-
- do
- {
- temp = curr;
- curr = curr->next;
- if (past_head)
- {
- fprintf (dest, "%s\t%s\n", temp->name, temp->store);
- }
- if (!past_head)
- past_head = TRUE;
- }
- while (curr != NULL);
- }
-
- /* --XREF list functions-- */
-
- BOOL exist_XREF (char *name)
- {
- XREF *curr;
-
- curr = xref->next;
- while (curr != NULL)
- {
- if (strcmp (curr->name, name) == 0)
- return (TRUE);
- else
- curr = curr->next;
- }
- return (FALSE);
- }
-
- void enter_XREF (char *name)
- {
- if (exist_XREF (name))
- return; /* already exists */
-
- if (strcmp (name, "_DOSBase") == 0)
- dosused = TRUE;
- if (strcmp (name, "_MathBase") == 0)
- mathffpused = TRUE;
- if (strcmp (name, "_MathTransBase") == 0)
- mathtransused = TRUE;
- if (strcmp (name, "_GfxBase") == 0)
- gfxused = TRUE;
- if (strcmp (name, "_IntuitionBase") == 0)
- intuitionused = TRUE;
- if (strcmp (name, "_TransBase") == 0)
- translateused = TRUE;
-
- /* allocate memory for a new node & name field */
- if ((new_xref = (XREF *) alloc (sizeof (XREF), MEMF_ANY)) == NULL)
- {
- printf ("Can't allocate memory for XREF node!\n");
- early_exit = TRUE;
- kill_all_lists ();
- cleanup ();
- }
-
- if ((new_xref->name = (char *) alloc (strlen (name) + 1, MEMF_ANY)) == NULL)
- {
- printf ("Can't allocate memory for XREF node name field!\n");
- early_exit = TRUE;
- kill_all_lists ();
- cleanup ();
- }
-
- /* fill XREF struct */
- strcpy (new_xref->name, name);
-
- new_xref->next = NULL;
- curr_xref->next = new_xref;
- curr_xref = curr_xref->next;
- }
-
- void write_xrefs (void)
- {
- BOOL past_head = FALSE;
- XREF *curr, *temp;
-
- fprintf (dest, "\n");
-
- curr = xref;
- do
- {
- temp = curr;
- curr = curr->next;
- if (past_head)
- {
- /* xdef or xref? */
- if (temp->name[0] != '*')
- {
- /* XREF */
- fprintf (dest, "\txref %s\n", temp->name);
- }
- else
- {
- /* XDEF -> first replace '*' with '_' */
- temp->name[0] = '_';
- fprintf (dest, "\txdef %s\n", temp->name);
- }
- }
- if (!past_head)
- past_head = TRUE;
- }
- while (curr != NULL);
- }
-
- /* --BASIC DATA list functions-- */
-
- void enter_BASDATA (char *literal)
- {
- basdatapresent = TRUE;
-
- /* allocate memory for a new node & data */
- if ((new_basdata = (BASDATA *) alloc (sizeof (BASDATA), MEMF_ANY)) == NULL)
- {
- printf ("Can't allocate memory for BASIC DATA node!\n");
- early_exit = TRUE;
- kill_all_lists ();
- cleanup ();
- }
-
- if ((new_basdata->literal = (char *) alloc (strlen (literal) + 1, MEMF_ANY)) == NULL)
- {
- printf ("Can't allocate memory for BASIC DATA node literal field!\n");
- early_exit = TRUE;
- kill_all_lists ();
- cleanup ();
- }
-
- /* fill BASDATA struct */
- strcpy (new_basdata->literal, literal);
-
- new_basdata->next = NULL;
- curr_basdata->next = new_basdata;
- curr_basdata = curr_basdata->next;
- }
-
- void write_basdata (void)
- {
- BOOL past_head = FALSE;
- BASDATA *curr, *temp;
-
- curr = basdata;
-
- if (curr->next != NULL)
- {
- fprintf (dest, "\n_BASICdata:\n");
- }
-
- do
- {
- temp = curr;
- curr = curr->next;
- if (past_head)
- {
- fprintf (dest, "\t%s\n", temp->literal);
- }
- if (!past_head)
- past_head = TRUE;
- }
- while (curr != NULL);
- }
-
-
- /* --structure functions-- */
-
- void find_structmem_tail (SYM * symtabitem)
- {
- /* find end of structdef member list. */
- tail_structmem = symtabitem->structmem;
- while (tail_structmem->next != NULL)
- tail_structmem = tail_structmem->next;
- }
-
- BOOL structmem_exist (SYM * symtabitem, char *name)
- {
- /* seek a structure
- member.
- */
-
- curr_structmem = symtabitem->structmem->next; /* head has no member data */
-
- while (curr_structmem != NULL)
- {
- if (strcmp (curr_structmem->name, name) == 0)
- return (TRUE);
- else
- curr_structmem = curr_structmem->next;
- }
-
- return (FALSE);
- }
-
- void add_struct_member (SYM * symtabitem, char *name, int mtype, SYM * structtype)
- {
- /* add a member to a
- structure definition.
- */
-
- if (structmem_exist (symtabitem, name))
- _error (61);
- else
- {
- /* add a unique member */
- if ((new_structmem = (STRUCM *) alloc (sizeof (STRUCM), MEMF_ANY)) == NULL)
- {
- printf ("Can't allocate memory for structdef node!\n");
- early_exit = TRUE;
- kill_all_lists ();
- cleanup ();
- }
- else
- {
- /* enter member data */
- strcpy (new_structmem->name, name);
- new_structmem->type = mtype;
- new_structmem->offset = symtabitem->size;
-
- /* link member into list */
- find_structmem_tail (symtabitem);
-
- new_structmem->next = NULL;
- tail_structmem->next = new_structmem;
- curr_structmem = new_structmem;
-
- /* increment size of structure
- and hence, find next offset.
- */
- switch (mtype)
- {
- case bytetype:
- symtabitem->size += 1;
- break;
- case shorttype:
- symtabitem->size += 2;
- break;
- case longtype:
- symtabitem->size += 4;
- break;
- case singletype:
- symtabitem->size += 4;
- break;
- case stringtype:
- symtabitem->size += MAXSTRLEN;
- curr_structmem->strsize = MAXSTRLEN;
- break;
- case structure:
- symtabitem->size += structtype->size;
- curr_structmem->strsize = structtype->size;
- break;
- }
- }
- }
- }
-